package net

import (
	"fmt"
	"net"
	"net/rpc"
	"time"
)

type NetTCP struct {
	Ln net.Listener

	out chan *NetCall

	pool     chan *rpc.Client
	poolsize int
}

type NetCall struct {
	Method string
	Addr   string

	Args  interface{}
	Reply interface{}

	Status  chan uint8
	Timeout time.Duration
}

func NewNetCall() *NetCall {

	c := new(NetCall)
	c.Status = make(chan uint8, 4)
	c.Timeout = 10e9

	return c
}

func (this *NetTCP) Listen(port string) (err error) {

	this.Ln, err = net.Listen("tcp", ":"+port)
	if err != nil {
		fmt.Println("listen error:", err)
	}

	return nil
}

func (this *NetTCP) Call(call *NetCall) {
	this.out <- call
}

func (this *NetTCP) sending() {

	var err error

	for p := range this.out {

		conn := <-this.pool

		if conn == nil {
			if conn, err = rpc.DialHTTP("tcp", p.Addr); err != nil {
				time.Sleep(1e9)
				this.pool <- nil
				this.out <- p
				continue
			}
		}

		//fmt.Println("sending", p)

		go func(this *NetTCP, conn *rpc.Client, p *NetCall) {

			rs := conn.Go(p.Method, p.Args, p.Reply, nil)

			select {
			case <-rs.Done:
				p.Status <- 1
			case <-time.After(p.Timeout):
				p.Status <- 9
			}

			if rs.Error != nil {
				this.pool <- nil
				this.out <- p
				return
			}

			this.pool <- conn

		}(this, conn, p)
	}
}
